open Type;
open Map;
open Actor;
(*{{{ Очередь*)
class manager map =
  object(self)
    value mutable queue:list (float * actor * event) = [];
    value mutable time:float = 0.0;
    value mutable map:map = map;
    value mutable repeat:bool = True;  
    method time:float = time;

    method add_actor (actor:actor) (x,y) =
      match map#cell (x,y) with
      [ `Occupation [] -> map#set_cell (x,y) (`Occupation [actor])
      | `Occupation _ -> failwith (Printf.sprintf "Point (%dx%d) already occupation" x y)
      | `Block -> failwith (Printf.sprintf "Point (%dx%d) blocked" x y)
      ];

    method del_actor (actor:actor) = 
      let (x,y) = map#position actor in
      match map#cell (x,y) with
      [ `Occupation [a] when a = actor -> map#set_cell (x,y) (`Occupation [])
      |  _ -> failwith (Printf.sprintf "Point (%dx%d) has't actor" x y)
      ];

    
    method add_event (timeout:float) (actor:actor) (event:event) = (*Добавить в очередь*)
      let (t:float) = time +. timeout in
      queue := 
        List.sort begin fun (lt,_,_) (rt,_,_) ->
          compare lt rt
        end [(t,actor,event)::queue];
      
    method clear = queue := []; (*Очистить очередь*)
    method stop = repeat := False; (*Остановить*)
    value delay = 2.0; (*Для визуального замедлния процессов*)
    method run = (*Основной цикл очереди*)
      let screen =  (* define some colors *)
        let (width,height) = map#size in
        Sdlvideo.set_video_mode ~w:(width*Video.pix_size) ~h:(height*Video.pix_size) ~bpp:32 [`HWSURFACE]
      in
      (
        Sdl.init [`VIDEO];
        at_exit Sdl.quit;
        Sdlvideo.fill_rect screen (Sdlvideo.map_RGB screen Sdlvideo.white);
        Sdlvideo.flip screen;
        let () = repeat := True in
        let m_print = Video.draw screen map in
        while (repeat) do
          match queue with
          [[] -> assert False
          |[(t,actor,event)::tl] ->
            let tm = t -. time in
            let (timeout,reaction) = Rule.dispath map (tm,actor,event) in
            (
              m_print (); 
              map#m_print;
              Printf.printf "System sleep %f\n%!" (tm*.delay);
              print_endline "------------------------------"; 
              ignore (Unix.select [] [] [] (tm*.delay));
              time := t;
              queue := tl;
              match reaction with
              [ `Die -> ()
              | _ -> self#add_event timeout actor reaction
              ]; 
            )
          ]
        done;
      );
end;
(*}}}*)
